package tests.subtask3;

import task.Board;
import solution.BoardFactory;
import task.Official;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

/**
 * Test distance calculations
 */
public class PublicDistanceTest {

    public PublicDistanceTest() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Before
    public void setUp() {
    }

    @After
    public void tearDown() {
    }

    @Test(timeout = 1000)
    public void simpleDistanceTest() {
        /* check all distances on the following board
         * y\x|  0|  1|  2|
         * ---+---+---+---+
         *   2|           |
         *    |  2   1   2|
         * ---+   +   +   +
         *   1|     G     |
         *    |  1  G0   1|
         * ---+   +   +   +
         *   0|           |
         *    |  2   1   2|
         * ---+---+---+---+
         */

        // move object
        Board board = BoardFactory.newBoard(3, 3);

        addPerimeter(board);

        // do something with the board
        Official official = board.addOfficial(1, 1, Official.Color.Green, Official.Color.Green);

        // check distances for all squares on the board
        assertEquals(0, board.getDistance(official, 1, 1));
        assertEquals(1, board.getDistance(official, 0, 1));
        assertEquals(1, board.getDistance(official, 1, 0));
        assertEquals(1, board.getDistance(official, 1, 2));
        assertEquals(1, board.getDistance(official, 2, 1));
        assertEquals(2, board.getDistance(official, 0, 2));
        assertEquals(2, board.getDistance(official, 2, 0));
        assertEquals(2, board.getDistance(official, 2, 2));
        assertEquals(2, board.getDistance(official, 2, 2));
    }

    @Test(timeout = 1000)
    public void complexDistanceTest() {
        /* check most squares on this board
         * don't check (1,0), this would spoil the surprise.
         * y\x|  0|  1|  2|
         * ---+---+---+---+
         *   2|###        |
         *    |###   3   2|
         * ---+   +   +   +
         *   1| R         |
         *    | G         |
         * ---+   +   +   +
         *   0| G         |
         *    | G    4   1|
         * ---+---+---+---+
         */
        // move object
        Board board = BoardFactory.newBoard(3, 3);

        addPerimeter(board);

        // do something with the board
        Official official = board.addOfficial(0, 0, Official.Color.Green, Official.Color.Green);
        board.addOfficial(0, 1, Official.Color.Green, Official.Color.Red);
        board.addBlock(0, 2);

        assertEquals(0, board.getDistance(official, 0, 0));
        assertEquals(Integer.MAX_VALUE, board.getDistance(official, 0, 1));
        assertEquals(Integer.MAX_VALUE, board.getDistance(official, 0, 2));
        assertEquals(Integer.MAX_VALUE, board.getDistance(official, 1, 1));
        assertEquals(3, board.getDistance(official, 1, 2));
        assertEquals(1, board.getDistance(official, 2, 0));
        assertEquals(Integer.MAX_VALUE, board.getDistance(official, 2, 1));
        assertEquals(2, board.getDistance(official, 2, 2));
    }

    private void addPerimeter(Board board) {
        int width = board.getWidth();
        int height = board.getHeight();
        for (int y = 0; y != height; ++y) {
            board.addWallWest(0, y);
            board.addWallEast(width - 1, y);
        }

        for (int x = 0; x != width; ++x) {
            board.addWallSouth(x, 0);
            board.addWallNorth(x, height - 1);
        }
    }
}
